Dilated convolutional stack.

  Features at different rates are computed independently using a 3 layer
  convolutional stack and added.

  Args:
    name: variable scope.
    x: 5-D Tensor.
    mid_channels: Number of output channels of the first layer in the conv
                  stack.
    output_channels: Number of output channels of the last layer.
    dilation_rates: A list of dilation rates.
    activation: Can be either "relu" or "gatu"
    dropout: dropout.
  Returns:
    output: 5-D Tensor.

def dilated_conv_stack(name, x, mid_channels, output_channels,
                       dilation_rates, activation="relu",
                       dropout=0.0):
  """Dilated convolutional stack.

  Features at different rates are computed independently using a 3 layer
  convolutional stack and added.

  Args:
    name: variable scope.
    x: 5-D Tensor.
    mid_channels: Number of output channels of the first layer in the conv
                  stack.
    output_channels: Number of output channels of the last layer.
    dilation_rates: A list of dilation rates.
    activation: Can be either "relu" or "gatu"
    dropout: dropout.
  Returns:
    output: 5-D Tensor.
  """
  with tf.variable_scope(name, reuse=tf.AUTO_REUSE):
    output = 0.0
    for dil_ind, dil_rate in enumerate(dilation_rates):
      # TODO(mechcoder) try (concat across channels + 1x1) modulo memory issues.
      curr_out = conv_stack("dil_%d" % dil_ind, x, mid_channels=mid_channels,
                            output_channels=output_channels, dilations=dil_rate,
                            activation=activation, dropout=dropout)
      output += curr_out
    return output