def collect(*args, **kwargs):
    '''
    collect(m1, m2, ...) yields a persistent map whose keys are the union of all keys in the given
      maps m1, m2, etc. and whose values are tuples containing each of the given maps (in provided
      order) that contain the given key. This function never evaluates the values in the maps so it
      implicitly supports laziness.

    The collect function fist passes its arguments to flatten_maps, so it is fine to pass lists or
    nested lists of maps to this function; all will be collected.
    '''
    args = flatten_maps(args, **kwargs)
    if len(args) == 0: return ps.m()
    m = {}
    for arg in args:
        for k in six.iterkeys(arg):
            if k in m: m[k].append(arg)
            else: m[k] = [arg]
    return ps.pmap({k:tuple(v) for (k,v) in six.iteritems(m)})