'This function creates all variables used by the network.
This allows us to share them between multiple calls to the loss
function and generation function.'

def _create_variables(self):

    var = dict()
    with tf.variable_scope('wavenet'):
        if (self.global_condition_cardinality is not None):
            with tf.variable_scope('embeddings'):
                layer = dict()
                layer['gc_embedding'] = create_embedding_table('gc_embedding', [self.global_condition_cardinality, self.global_condition_channels])
                var['embeddings'] = layer
        with tf.variable_scope('causal_layer'):
            layer = dict()
            if self.scalar_input:
                initial_channels = 1
                initial_filter_width = self.initial_filter_width
            else:
                initial_channels = self.quantization_channels
                initial_filter_width = self.filter_width
            layer['filter'] = create_variable('filter', [initial_filter_width, initial_channels, self.residual_channels])
            var['causal_layer'] = layer
        var['dilated_stack'] = list()
        with tf.variable_scope('dilated_stack'):
            for (i, dilation) in enumerate(self.dilations):
                with tf.variable_scope('layer{}'.format(i)):
                    current = dict()
                    current['filter'] = create_variable('filter', [self.filter_width, self.residual_channels, self.dilation_channels])
                    current['gate'] = create_variable('gate', [self.filter_width, self.residual_channels, self.dilation_channels])
                    current['dense'] = create_variable('dense', [1, self.dilation_channels, self.residual_channels])
                    current['skip'] = create_variable('skip', [1, self.dilation_channels, self.skip_channels])
                    if (self.global_condition_channels is not None):
                        current['gc_gateweights'] = create_variable('gc_gate', [1, self.global_condition_channels, self.dilation_channels])
                        current['gc_filtweights'] = create_variable('gc_filter', [1, self.global_condition_channels, self.dilation_channels])
                    if self.use_biases:
                        current['filter_bias'] = create_bias_variable('filter_bias', [self.dilation_channels])
                        current['gate_bias'] = create_bias_variable('gate_bias', [self.dilation_channels])
                        current['dense_bias'] = create_bias_variable('dense_bias', [self.residual_channels])
                        current['skip_bias'] = create_bias_variable('slip_bias', [self.skip_channels])
                    var['dilated_stack'].append(current)
        with tf.variable_scope('postprocessing'):
            current = dict()
            current['postprocess1'] = create_variable('postprocess1', [1, self.skip_channels, self.skip_channels])
            current['postprocess2'] = create_variable('postprocess2', [1, self.skip_channels, self.quantization_channels])
            if self.use_biases:
                current['postprocess1_bias'] = create_bias_variable('postprocess1_bias', [self.skip_channels])
                current['postprocess2_bias'] = create_bias_variable('postprocess2_bias', [self.quantization_channels])
            var['postprocessing'] = current
    return var
