def stacked_bilstm(input_emb, input_len, hidden_size, num_layers, dropout_ratio,
                   mode, use_cudnn=None):
  """Encode inputs via stacked bidirectional LSTMs with residual connections.

  Args:
    input_emb: <float32> [batch_size, sequence_length, emb]
    input_len: <int32> [batch_size]
    hidden_size: Size of each LSTM layer.
    num_layers: Number of LSTM layers.
    dropout_ratio: Probability of dropout out dimensions of each hidden layer.
    mode: One of the keys from tf.estimator.ModeKeys.
    use_cudnn: Specify the use of cudnn. `None` denotes automatic selection.

  Returns:
    output_emb: <float32> [batch_size, sequence_length, emb]
  """
  # cuDNN expects time-major inputs, so we transpose before and after.
  input_emb = tf.transpose(input_emb, [1, 0, 2])
  if use_cudnn is None:
    use_cudnn = tf.test.is_gpu_available(cuda_only=True)

  for i in range(num_layers):
    with tf.variable_scope("lstm_{}".format(i)):
      if mode == tf_estimator.ModeKeys.TRAIN:
        input_emb = tf.nn.dropout(input_emb, 1.0 - dropout_ratio)

      output_emb = []
      for is_fwd in (True, False):
        with tf.variable_scope("fw" if is_fwd else "bw"):
          output_emb.append(_single_lstm(
              input_emb=input_emb,
              input_len=input_len,
              hidden_size=hidden_size,
              is_fwd=is_fwd,
              use_cudnn=use_cudnn))
      output_emb = tf.concat(output_emb, -1)
      if i == 0:
        input_emb = output_emb
      else:
        # Add residual connection after the first layer.
        input_emb += output_emb

  # cuDNN expects time-major inputs, so we transpose before and after.
  output_emb = tf.transpose(input_emb, [1, 0, 2])
  return output_emb
Encode inputs via stacked bidirectional LSTMs with residual connections.

  Args:
    input_emb: <float32> [batch_size, sequence_length, emb]
    input_len: <int32> [batch_size]
    hidden_size: Size of each LSTM layer.
    num_layers: Number of LSTM layers.
    dropout_ratio: Probability of dropout out dimensions of each hidden layer.
    mode: One of the keys from tf.estimator.ModeKeys.
    use_cudnn: Specify the use of cudnn. `None` denotes automatic selection.

  Returns:
    output_emb: <float32> [batch_size, sequence_length, emb]
  
language/common/layers/cudnn_layers.py