Parameters
        ----------
        inputs : NDArray
            Shape (batch_size, sequence_length, max_character_per_token)
            of character ids representing the current batch.
        states : (list of list of NDArray, list of list of NDArray)
            The states. First tuple element is the forward layer states, while the second is
            the states from backward layer. Each is a list of states for each layer.
            The state of each layer has a list of two initial tensors with
            shape (batch_size, proj_size) and (batch_size, hidden_size).
        mask :  NDArray
            Shape (batch_size, sequence_length) with sequence mask.

        Returns
        -------
        output : list of NDArray
            A list of activations at each layer of the network, each of shape
            (batch_size, sequence_length, embedding_size)
        states : (list of list of NDArray, list of list of NDArray)
            The states. First tuple element is the forward layer states, while the second is
            the states from backward layer. Each is a list of states for each layer.
            The state of each layer has a list of two initial tensors with
            shape (batch_size, proj_size) and (batch_size, hidden_size).

def hybrid_forward(self, F, inputs, states=None, mask=None):
        # pylint: disable=arguments-differ
        """
        Parameters
        ----------
        inputs : NDArray
            Shape (batch_size, sequence_length, max_character_per_token)
            of character ids representing the current batch.
        states : (list of list of NDArray, list of list of NDArray)
            The states. First tuple element is the forward layer states, while the second is
            the states from backward layer. Each is a list of states for each layer.
            The state of each layer has a list of two initial tensors with
            shape (batch_size, proj_size) and (batch_size, hidden_size).
        mask :  NDArray
            Shape (batch_size, sequence_length) with sequence mask.

        Returns
        -------
        output : list of NDArray
            A list of activations at each layer of the network, each of shape
            (batch_size, sequence_length, embedding_size)
        states : (list of list of NDArray, list of list of NDArray)
            The states. First tuple element is the forward layer states, while the second is
            the states from backward layer. Each is a list of states for each layer.
            The state of each layer has a list of two initial tensors with
            shape (batch_size, proj_size) and (batch_size, hidden_size).
        """

        type_representation = self._elmo_char_encoder(inputs)
        type_representation = type_representation.transpose(axes=(1, 0, 2))
        lstm_outputs, states = self._elmo_lstm(type_representation, states, mask)
        lstm_outputs = lstm_outputs.transpose(axes=(0, 2, 1, 3))
        type_representation = type_representation.transpose(axes=(1, 0, 2))

        # Prepare the output. The first layer is duplicated.
        output = F.concat(*[type_representation, type_representation], dim=-1)
        if mask is not None:
            output = output * mask.expand_dims(axis=-1)
        output = [output]
        output.extend([layer_activations.squeeze(axis=0) for layer_activations
                       in F.split(lstm_outputs, self._num_layers, axis=0)])
        return output, states