You can use something like the following. I'm not sure from your current approach if this is exactly your desired output or not since it seems to contain a lot of redundant information.
df %>%
gather(val, var, -ID) %>%
extract(val, c("value", "time"), regex = "([a-z]+)([0-9]+)") %>%
spread(value, var)
# # A tibble: 10 × 4
# ID time letter measure
# *
# 1 1 1 a 1
# 2 1 2 f 6
# 3 2 1 b 2
# 4 2 2 g 7
# 5 3 1 c 3
# 6 3 2 h 8
# 7 4 1 d 4
# 8 4 2 i 9
# 9 5 1 e 5
# 10 5 2 j 10
This is much more easily done with melt + patterns from "data.table":
library(data.table)
melt(as.data.table(df), measure.vars = patterns("measure", "letter"))
Or you can be old-school and just use reshape from base R. Note, however, that base R's reshape does not like "tibbles", so you have to convert it with as.data.frame).
reshape(as.data.frame(df), direction = "long", idvar = "ID",
varying = 2:ncol(df), sep = "")