takes the rel for the each
function applyEachOptimization(rel){

	var originalRel = rel
	rel = JSON.parse(JSON.stringify(rel))	
	
	//console.log('rel: ' + JSON.stringify(rel))
	try{
		var newImplicits = [rel.params[1].implicits[0]]
		var bindingsUsed = _.extend({}, rel.params[1].bindingsUsed)
		//1. extract macro params to one or more ~:property maps
		var maps = []
		var failed = false
		var newMacroExpr = replaceMacroPropertyExpressions(rel.params[1].expr, rel.params[1].implicits, function(macroPropertyExpr){
			if(macroPropertyExpr.schemaType.type === 'map'){
				failed = true
				return
			}
			var uid = 'extproperty_'+Math.random()
			var bu = {}
			bu[uid] = true
			var m = {
				type: 'view', 
				view: 'map', 
				params: [
					rel.params[0],
					{	
						type: 'macro', 
						manyImplicits: 1, 
						expr: {type: 'param', name: uid, schemaType: rel.params[0].schemaType.members}, 
						bindingsUsed: bu, 
						implicits: [uid], 
						schemaType: rel.params[0].schemaType.members,
						implicitTypes: [rel.params[0].schemaType.members]
					},{
						type: 'macro', 
						manyImplicits: 1, 
						expr: JSON.parse(JSON.stringify(macroPropertyExpr)), 
						bindingsUsed: bu, 
						implicits: [rel.params[1].implicits[0]], 
						schemaType: macroPropertyExpr.schemaType,
						implicitTypes: [rel.params[1].implicitTypes[0]]
					}
				], 
				willBeOptimized: true,
				uid: uid
			}
			m.schemaType = {type: 'map', key: m.params[1].schemaType, value: m.params[2].schemaType}
			maps.push(applyEachOptimizationToView(m))
			newImplicits.push(uid)
			bindingsUsed[uid] = true
			_.assertDefined(macroPropertyExpr.schemaType)
			return {type: 'param', name: uid, schemaType: macroPropertyExpr.schemaType}
		})
		if(failed) return originalRel
		var newMacro = {
			type: 'macro',
			expr: newMacroExpr,
			manyImplicits: newImplicits.length,
			implicits: newImplicits,
			implicitTypes: [rel.params[0].schemaType.members],
			bindingsUsed: bindingsUsed,//newImplicits
			schemaType: newMacroExpr.schemaType
		}
		//console.log('created m: ' + JSON.stringify(newMacro, null, 2))
		return {
			type: 'view',
			view: 'each-optimization',
			params: [rel.params[0], newMacro].concat(maps),
			schemaType: rel.schemaType,
			code: rel.code
		}
	}catch(e){
		//console.log('could not optimize each + e.stack)
		return originalRel
	}
}