Binds the symbols to construct executors. This is necessary before one
        can perform computation with the module.

        Parameters
        ----------
        data_shapes : list of (str, tuple) or DataDesc objects
            Typically is ``data_iter.provide_data``. Can also be a list of
            (data name, data shape).
        label_shapes : list of (str, tuple) or DataDesc objects
            Typically is ``data_iter.provide_label``. Can also be a list of
            (label name, label shape).
        for_training : bool
            Default is ``True``. Whether the executors should be bind for training.
        inputs_need_grad : bool
            Default is ``False``. Whether the gradients to the input data need to be computed.
            Typically this is not needed. But this might be needed when implementing composition
            of modules.
        force_rebind : bool
            Default is ``False``. This function does nothing if the executors are already
            bound. But with this ``True``, the executors will be forced to rebind.
        shared_module : Module
            Default is ``None``. This is used in bucketing. When not ``None``, the shared module
            essentially corresponds to a different bucket -- a module with different symbol
            but with the same sets of parameters (e.g. unrolled RNNs with different lengths).
        grad_req : str, list of str, dict of str to str
            Requirement for gradient accumulation. Can be 'write', 'add', or 'null'
            (default to 'write').
            Can be specified globally (str) or for each argument (list, dict).

        Examples
        --------
        >>> # An example of binding symbols.
        >>> mod.bind(data_shapes=[('data', (1, 10, 10))])
        >>> # Assume train_iter is already created.
        >>> mod.bind(data_shapes=train_iter.provide_data, label_shapes=train_iter.provide_label)

def bind(self, data_shapes, label_shapes=None, for_training=True,
             inputs_need_grad=False, force_rebind=False, shared_module=None,
             grad_req='write'):
        """Binds the symbols to construct executors. This is necessary before one
        can perform computation with the module.

        Parameters
        ----------
        data_shapes : list of (str, tuple) or DataDesc objects
            Typically is ``data_iter.provide_data``. Can also be a list of
            (data name, data shape).
        label_shapes : list of (str, tuple) or DataDesc objects
            Typically is ``data_iter.provide_label``. Can also be a list of
            (label name, label shape).
        for_training : bool
            Default is ``True``. Whether the executors should be bind for training.
        inputs_need_grad : bool
            Default is ``False``. Whether the gradients to the input data need to be computed.
            Typically this is not needed. But this might be needed when implementing composition
            of modules.
        force_rebind : bool
            Default is ``False``. This function does nothing if the executors are already
            bound. But with this ``True``, the executors will be forced to rebind.
        shared_module : Module
            Default is ``None``. This is used in bucketing. When not ``None``, the shared module
            essentially corresponds to a different bucket -- a module with different symbol
            but with the same sets of parameters (e.g. unrolled RNNs with different lengths).
        grad_req : str, list of str, dict of str to str
            Requirement for gradient accumulation. Can be 'write', 'add', or 'null'
            (default to 'write').
            Can be specified globally (str) or for each argument (list, dict).

        Examples
        --------
        >>> # An example of binding symbols.
        >>> mod.bind(data_shapes=[('data', (1, 10, 10))])
        >>> # Assume train_iter is already created.
        >>> mod.bind(data_shapes=train_iter.provide_data, label_shapes=train_iter.provide_label)
        """
        raise NotImplementedError()