'Sum together the expert output, multiplied by the corresponding gates.
Args:
expert_out: a list of `num_experts` `Tensor`s, each with shape
`[expert_batch_size_i, <extra_output_dims>]`.
multiply_by_gates: a boolean.
Returns:
a list of num_datashards `Tensor`s with shapes
`[batch_size[d], <extra_output_dims>]`.'

def Combine(self, expert_out, multiply_by_gates=True):

    expert_part_sizes = tf.unstack(tf.stack([self._dispatchers[d].part_sizes for d in xrange(self._num_datashards)]), num=self._num_experts, axis=1)
    expert_output_parts = Parallel(self._expert_devices, tf.split, expert_out, expert_part_sizes)
    expert_output_parts_t = TransposeListOfLists(expert_output_parts)
    ret = []
    for d in xrange(self._num_datashards):
        with tf.device(self._datashard_devices[d]):
            ret.append(self._dispatchers[d].Combine(ConvertGradientToTensor(tf.concat(expert_output_parts_t[d], 0)), multiply_by_gates=multiply_by_gates))
    return ret
