I've grown so accustomed to using tibbles, I totally forgot about stringsAsFactors = false. Thanks @hadley for making that possible. Also, thanks @danr for your feedback.
For those watching at home:
library(tidyverse)
df3 <- data.frame(c1 = letters[1:5], c2 = 5:9, c3 = LETTERS[5:9], stringsAsFactors = FALSE)
df3 %>% mutate_if(is.character, str_replace_all, pattern = '[aeiouAEIOU]', replacement = '%%%%')
#> c1 c2 c3
#> 1 %%%% 5 %%%%
#> 2 b 6 F
#> 3 c 7 G
#> 4 d 8 H
#> 5 %%%% 9 %%%%