function doInParallel_aggregateErrors(items, beginProcessItem) {
        var errors = [];

        var masterDeferred = new $.Deferred();

        var parallelResult = doInParallel(
            items,
            function (item, i) {
                var itemResult = beginProcessItem(item, i);
                itemResult.fail(function (error) {
                    errors.push({ item: item, error: error });
                });
                return itemResult;
            },
            false
        );

        parallelResult
            .done(function () {
                masterDeferred.resolve();
            })
            .fail(function () {
                masterDeferred.reject(errors);
            });

        return masterDeferred.promise();
    }
Executes a series of tasks in parallel, saving up error info from any that fail along the way.
Returns a Promise that is only resolved/rejected once all tasks are complete. This is
essentially a wrapper around doInParallel(..., false).

If one or more tasks failed, the entire "master" promise is rejected at the end - with one
argument: an array objects, one per failed task. Each error object contains:
 - item -- the entry in items whose task failed
 - error -- the first argument passed to the fail() handler when the task failed

@param {!Array.<*>} items
@param {!function(*, number):Promise} beginProcessItem
@return {$.Promise}