def bootstrap_sample_all(experiments, bootstrap_rng, normalize=True):
    """
    Generate bootstrap samples of estimated progress curves (normalized
    and unnormalized) from a set of experiments.

    Arguments
    ---------
    experiments : list of list of wrapper_base.Experiment objects
        experiments of different solvers and/or problems
    bootstrap_rng : MRG32k3a object
        random number generator to use for bootstrapping
    normalize : bool
        normalize progress curves w.r.t. optimality gaps?

    Returns
    -------
    bootstrap_curves : list of list of list of wrapper_base.Curve objects
        bootstrapped estimated objective curves or estimated progress curves
        of all solutions from all macroreplications
    """
    n_solvers = len(experiments)
    n_problems = len(experiments[0])
    bootstrap_curves = [[[] for _ in range(n_problems)] for _ in range(n_solvers)]
    # Obtain a bootstrap sample from each experiment.
    for solver_idx in range(n_solvers):
        for problem_idx in range(n_problems):
            experiment = experiments[solver_idx][problem_idx]
            bootstrap_curves[solver_idx][problem_idx] = experiment.bootstrap_sample(bootstrap_rng, normalize)
            # Reset substream for next solver-problem pair.
            bootstrap_rng.reset_substream()
    # Advance substream of random number generator to prepare for next bootstrap sample.
    bootstrap_rng.advance_substream()
    return bootstrap_curves