'Applies a given function to a given stash.
:param state_func:  A function to apply to every state. Should take a state and return a state. The returned state
will take the place of the old state. If the function *doesn\'t* return a state, the old
state will be used. If the function returns a list of states, they will replace the original
states.
:param stash_func:  A function to apply to the whole stash. Should take a list of states and return a list of
states. The resulting list will replace the stash.
If both state_func and stash_func are provided state_func is applied first, then stash_func
is applied on the results.
:returns:           The resulting SimulationManager.
:rtype:             SimulationManager'

def apply(self, state_func=None, stash_func=None, stash=None):

    stash = ('active' if (stash is None) else stash)
    new_stashes = self._copy_stashes()
    new_states = new_stashes[stash]
    if (state_func is not None):
        new_new_states = []
        for p in new_states:
            np = state_func(p)
            if isinstance(np, SimState):
                new_new_states.append(np)
            elif isinstance(np, (list, tuple, set)):
                new_new_states.extend(np)
            else:
                new_new_states.append(p)
        new_states = new_new_states
    if (stash_func is not None):
        new_states = stash_func(new_states)
    new_stashes[stash] = new_states
    return self._successor(new_stashes)
