'Add a model parameter w.r.t. we expect to compute gradients.
_AddParam creates both regular parameters (usually for training) and
averaged nodes (usually for inference). It returns one or the other based
on the \'return_average\' arg.
Args:
shape: int list, tensor shape of the parameter to create
dtype: tf.DataType, data type of the parameter
name: string, name of the parameter in the TF graph
initializer: optional initializer for the paramter
return_average: if False, return parameter otherwise return moving average
Returns:
parameter or averaged parameter'

def _AddParam(self, shape, dtype, name, initializer=None, return_average=False):

    if (name not in self.params):
        step = tf.cast(self.GetStep(), tf.float32)
        with tf.name_scope(self._param_scope):
            self.params[name] = tf.get_variable(name, shape, dtype, initializer)
            param = self.params[name]
            if (initializer is not None):
                self.inits[name] = state_ops.init_variable(param, initializer)
            if (self._averaging_decay == 1):
                logging.info('Using    vanilla    averaging    of    parameters.')
                ema = tf.train.ExponentialMovingAverage(decay=(step / (step + 1.0)), num_updates=None)
            else:
                ema = tf.train.ExponentialMovingAverage(decay=self._averaging_decay, num_updates=step)
            self._averaging[(name + '_avg_update')] = ema.apply([param])
            self.variables[(name + '_avg_var')] = ema.average(param)
            self.inits[(name + '_avg_init')] = state_ops.init_variable(ema.average(param), tf.zeros_initializer())
    return (self.variables[(name + '_avg_var')] if return_average else self.params[name])
