class_docstr: A distributed version of SparseDispatcher.
  
  Instead of one batch of input examples, we simultaneously process
  a list of num_datashards batches of input examples.  The per-expert
  `Tensor`s contain a combination of examples from the different datashards.
  
  Each datashard is associated with a particular device and each expert is
  associated with a particular device.  All per-datashard and per-expert
  `Tensor`s are created on those devices.  There is no single-device bottleneck.
class_docstr_tok: ["A","distributed","version","of","SparseDispatcher",".","Instead","of","one","batch","of","input","examples",",","we","simultaneously","process","a","list","of","num_datashards","batches","of","input","examples",".","The","per-expert","`","Tensor","`","s","contain","a","combination","of","examples","from","the","different","datashards",".","Each","datashard","is","associated","with","a","particular","device","and","each","expert","is","associated","with","a","particular","device",".","All","per-datashard","and","per-expert","`","Tensor","`","s","are","created","on","those","devices",".","There","is","no","single-device","bottleneck","."]
docstr: 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>]`.
docstr_tok: ["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",">","]","`","."]
code: def combine(self, expert_out, multiply_by_gates=True):
      """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>]`.
      """
      expert_part_sizes = tf.unstack(
          tf.stack([d.part_sizes for d in self._dispatchers]),
          num=self._ep.n,
          axis=1,
      )
      # list of lists of shape [num_experts][num_datashards]
      expert_output_parts = self._ep(
          tf.split, expert_out, expert_part_sizes
      )
      expert_output_parts_t = transpose_list_of_lists(
          expert_output_parts
      )
  
      def my_combine(dispatcher, parts):
          return dispatcher.combine(
              common_layers.convert_gradient_to_tensor(
                  tf.concat(parts, 0)
              ),
              multiply_by_gates=multiply_by_gates,
          )
  
      return self._dp(
          my_combine, self._dispatchers, expert_output_parts_t
      )
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import functools
  import math
  import six
  from six.moves import range
  from six.moves import zip
  from tensor2tensor.layers import common_layers
  from tensor2tensor.layers.vq_discrete import DiscreteBottleneck
  import tensorflow.compat.v1
label_desc: Use image node_id 3 for calling the DistributedSparseDispatcher obj's underlying member method code with example usage: obj.combine(expert_out, multiply_by_gates) and returns: self, dispatcher