docs: def apply_groupby_func(func, *args):
      """Apply a dataset or datarray level function over GroupBy, Dataset,
      DataArray, Variable and/or ndarray objects.
      """
      from .groupby import GroupBy, peek_at
      from .variable import Variable
  
      groupbys = [arg for arg in args if isinstance(arg, GroupBy)]
      assert groupbys, 'must have at least one groupby to iterate over'
      first_groupby = groupbys[0]
      if any(not first_groupby._group.equals(gb._group) for gb in groupbys[1:]):
          raise ValueError('apply_ufunc can only perform operations over '
                           'multiple GroupBy objets at once if they are all '
                           'grouped the same way')
  
      grouped_dim = first_groupby._group.name
      unique_values = first_groupby._unique_coord.values
  
      iterators = []
      for arg in args:
          if isinstance(arg, GroupBy):
              iterator = (value for _, value in arg)
          elif hasattr(arg, 'dims') and grouped_dim in arg.dims:
              if isinstance(arg, Variable):
                  raise ValueError(
                      'groupby operations cannot be performed with '
                      'xarray.Variable objects that share a dimension with '
                      'the grouped dimension')
              iterator = _iter_over_selections(arg, grouped_dim, unique_values)
          else:
              iterator = itertools.repeat(arg)
          iterators.append(iterator)
  
      applied = (func(*zipped_args) for zipped_args in zip(*iterators))
      applied_example, applied = peek_at(applied)
      combine = first_groupby._combine
      if isinstance(applied_example, tuple):
          combined = tuple(combine(output) for output in zip(*applied))
      else:
          combined = combine(applied)
      return combined