import tensorflow as tf

        export_feat_tensors = {}

        # Input tensors
        feats_audio_nunroll = tf.placeholder(dtype, shape=[batch_size, rnn_nunroll + zack_hack, audio_context_len, audio_nbands, audio_nchannels], name='feats_audio')
        feats_other_nunroll = tf.placeholder(dtype, shape=[batch_size, rnn_nunroll, nfeats], name='feats_other')
        print('feats_audio: {}'.format(feats_audio_nunroll.get_shape()))
        print('feats_other: {}'.format(feats_other_nunroll.get_shape()))

        if mode != 'gen':
            targets_nunroll = tf.placeholder(dtype, shape=[batch_size, rnn_nunroll])
            # TODO: tf.ones acts as an overridable placeholder but this is still awkward
            target_weights_nunroll = tf.ones([batch_size, rnn_nunroll], dtype)

        # Reshape input tensors to remove nunroll dim; will briefly restore later during RNN if necessary
        if cnn_rnn_zack:
            feats_audio = tf.reshape(feats_audio_nunroll, shape=[batch_size, rnn_nunroll + zack_hack, audio_nbands, audio_nchannels])
        else:
            feats_audio = tf.reshape(feats_audio_nunroll, shape=[batch_size * rnn_nunroll, audio_context_len, audio_nbands, audio_nchannels])
        feats_other = tf.reshape(feats_other_nunroll, shape=[batch_size * rnn_nunroll, nfeats])
        if mode != 'gen':
            targets = tf.reshape(targets_nunroll, shape=[batch_size * rnn_nunroll])
            target_weights = tf.reshape(target_weights_nunroll, shape=[batch_size * rnn_nunroll])

        # CNN
        cnn_output = feats_audio
        if do_cnn:
            layer_last = feats_audio
            nfilt_last = audio_nchannels
            for i, ((ntime, nband, nfilt), (ptime, pband)) in enumerate(zip(cnn_filter_shapes, cnn_pool)):
                layer_name = 'cnn_{}'.format(i)
