I know this is an old problem, but I recently had the same problem, and I came up with this solution that I wanted to share. The trick is to collect the datasets needed for individual geom_tile() plots in a nested frame using nest() from tidyr , and then use the map2() function from the purrr package and the wrapper function to create separate plots:
library(tidyverse) pp <- function (n,r=4) { x <- seq(-r*pi, r*pi, len=n) df <- expand.grid(x=x, y=x) df$r <- sqrt(df$x^2 + df$y^2) df$z <- cos(df$r^2)*exp(-df$r/6) df } tmp <- pp(20) tmp$type <- rep(1:4,each=nrow(tmp)/4) tmp$z <- tmp$z*(10^(tmp$type)) plot_func <- function(df, name) { ggplot(data = df, aes(x = x, y = y, fill = z)) + geom_tile() + scale_fill_continuous(name = name) } nested_tmp <- tmp %>% group_by(type) %>% nest() %>% mutate(plots = map2(data, type, plot_func)) gridExtra::grid.arrange(grobs = nested_tmp$plots)

The nested framework contains two columns of the list that contain data sets and graphs:
> nested_tmp # A tibble: 4 × 3 type data plots <int> <list> <list> 1 1 <tibble [100 × 4]> <S3: gg> 2 2 <tibble [100 × 4]> <S3: gg> 3 3 <tibble [100 × 4]> <S3: gg> 4 4 <tibble [100 × 4]> <S3: gg>
It is very easy to change plot_func() to fine tune the graphs.
source share